package controller;

import Enums.State;
import java.io.Serializable;
import java.util.Observable;
import javax.swing.JOptionPane;
import javax.swing.text.PlainDocument;
import model.Model_Image_Line;
import org.jfree.chart.JFreeChart;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

/**
 * RunnableObject für den Thread, der die Berechnung der Evolution übernimmt.
 */
public class LinePainter extends Observable implements Runnable, Serializable {

    private boolean paused=false;
    private Model_Image_Line image_line;
    private Controller_Fitness controller_fitness;
    private PlainDocument log;
    JFreeChart chart;
    XYSeries series;

    /**
     * Konstruktor für den line_painter
     * @param model_image_line
     * @param controller_Fitness
     * @param model_log
     */
    public LinePainter(Model_Image_Line model_image_line, Controller_Fitness controller_Fitness, PlainDocument model_log, JFreeChart chart) {
        this.controller_fitness = controller_Fitness;
        this.image_line = model_image_line;
        this.log = model_log;
        this.chart = chart;
        series = ((XYSeriesCollection) chart.getXYPlot().getDataset()).getSeries(0);
        series.clear();
    }

    /**
     * Endlosschleife, die solange läuft bis die Evolution pausiert oder abgebrochen wird.
     */
    @Override
    public void run() {
        try {
            log.insertString(log.getEndPosition().getOffset(), "Evolution wurde gestartet.\n", null);
            double fittval;
            int i = this.image_line.getGenoConf().getGenerationNr();
            while (true) {
                controller_fitness.runEvolution(i);
                fittval = image_line.getGenotype().getFittestChromosome().getFitnessValue();                
                series.add(i, fittval); //fügt dem Diagramm den den Fitnesswert zu
                i++;
                if (isPaused()) {
                    synchronized (this) {
                        while (isPaused()) {
                            Controller.getInstance().setState(State.waiting);
                            log.insertString(log.getEndPosition().getOffset(), "Evolution wird pausiert.\n", null);
                            wait();
                            Controller.getInstance().setState(State.running);
                            log.insertString(log.getEndPosition().getOffset(), "Evolution wird fortgesetzt.\n", null);
                        }
                    }
                }
            }
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(null, ex.toString(), "ERROR", JOptionPane.ERROR_MESSAGE);
        }
    }

    /**
     * pausiert den Berechnungsprozess wenn dieser läuft
     * startet ihn erneut, wenn er pausiert ist.
     */
    protected synchronized void pauseRestart() {
        paused = !paused;
        if (!paused) {
            notify();
        }
    }

    /**
     * 
     * @return
     */
    public synchronized boolean isPaused () {
        return paused;
    }
}
